package com.wzy.controller;

import com.wzy.utils.JDBCUtils;
import com.wzy.utils.ThreadPoolComponent;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Auther: wzy
 * @Date: 2021/11/28/10:27
 * @Description: 使用多线程向数据库插入数据demo
 */
public class TestManyThreadInsert {
    static int poolSize = Runtime.getRuntime().availableProcessors();
    public static void main(String[] args) throws SQLException {
        long start = System.currentTimeMillis();
        createThreadPoolBatch();
        long end = System.currentTimeMillis();
        System.out.println((end - start) / 1000 + "秒");
//        formatList();
    }

    private static void getConnection() {
        Connection conn = JDBCUtils.getConnection();
        ResultSet resultSet = null;
        PreparedStatement preparedStatement = null;
        try {
            String sql = "INSERT  INTO  user  (name,salary) values(?,?)";
            preparedStatement = conn.prepareStatement(sql);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            JDBCUtils.closeResouces(resultSet, preparedStatement, conn);
        }
    }

    private static void toDb(List<Integer> dates) {
        Connection conn = JDBCUtils.getConnection();
        ResultSet resultSet = null;
        PreparedStatement preparedStatement = null;
        try {
            String sql = "INSERT  INTO  user  (name,salary) values(?,?)";
            preparedStatement = conn.prepareStatement(sql);
            preparedStatement.setInt(1, dates.get(0));
            preparedStatement.setInt(2, dates.get(1));
            preparedStatement.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            System.out.println("向数据库插入数据库数据失败");
        } finally {
            JDBCUtils.closeResouces(resultSet, preparedStatement, conn);
        }
    }

    private static void toDbBatch(String date) {
            Connection conn = JDBCUtils.getConnection();
            ResultSet resultSet = null;
            Statement preparedStatement = null;
            try {
                StringBuilder sb = new StringBuilder("INSERT INTO user(name,salary) VALUES  ");
                sb.append(date);
                System.out.println(sb.toString());
                preparedStatement = conn.createStatement();
                preparedStatement.execute(sb.toString());
            } catch (SQLException throwables) {
                throwables.printStackTrace();
                System.out.println("向数据库插入数据库数据失败");
            } finally {
                JDBCUtils.closeResouces(resultSet, preparedStatement, conn);
            }
    }

    public static void createThreadPool() {
        List<List<Integer>> lists = getDate();
        ExecutorService executorService = new ThreadPoolComponent().getFullIOExecutorService(5, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(80), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < lists.size(); i++) {
            int finalI = i;
            executorService.execute(() -> {
                System.out.println(Thread.currentThread().getName() + "---" + finalI);
                toDb(lists.get(finalI));
            });
        }
        executorService.shutdown();
    }

    public static void createThreadPoolBatch() {
        List<String> lists = formatList();
        ExecutorService executorService = new ThreadPoolComponent().getFullIOExecutorService(5, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(80), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < lists.size(); i++) {
            int finalI = i;
            executorService.execute(() -> {
                System.out.println(Thread.currentThread().getName() + "---" + finalI);
                toDbBatch(lists.get(finalI));
            });
        }
        executorService.shutdown();

    }

    /**
     * 自定义线程池
     *
     * @author wzy
     * @date 2021/11/28 12:07
     */
    public static void createThreadPoolByMySelf() {
        List<List<Integer>> lists = getDate();
        ExecutorService executorService = new ThreadPoolExecutor(5, 60, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(80), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < lists.size(); i++) {
            int finalI = i;
            executorService.execute(() -> {
                System.out.println(Thread.currentThread().getName() + "---" + finalI);
                toDb(lists.get(finalI));
            });
            toDb(lists.get(i));
        }
        executorService.shutdown();

    }

    public static void testCreateThreadPool1() {

        ExecutorService executorService = new ThreadPoolComponent().getFullIOExecutorService(5, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(80), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 500; i++) {
            executorService.execute(() -> {
                System.out.println(Thread.currentThread().getName());
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
    }

    public static void testCreateThreadPool2() {

        ExecutorService executorService = new ThreadPoolExecutor(5, 60, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(80), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 0; i < 500; i++) {

            executorService.execute(() -> {
                System.out.println(Thread.currentThread().getName());
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
    }

    public static List<List<Integer>> getDate() {
        List<List<Integer>> lists = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            List<Integer> list = new ArrayList<>();
            int name = i;
            int salary = (500 + i * 10);
            list.add(name);
            list.add(salary);
            lists.add(list);
        }
        return lists;
    }
    public static List<String> formatList(){
        List<List<Integer>> lists = getDate();
        int count =1000;
        int num = 1;
        List<String> collect = lists.parallelStream().map(x -> x.stream().parallel().map(s -> String.valueOf(s)).collect(Collectors.joining(",", "(", ")"))).collect(Collectors.toList());
        if (collect.size() > 500){
            num = (count+collect.size() - 1)/count;
        }
        List<String> list = new ArrayList<>();
        //parallel 并行流不保证有序，需要保证有序可以去掉
        Stream.iterate(0,n -> n+1).limit(num).parallel().forEach(a ->{
            String collect1 = collect.stream().skip(a * count).limit(count).collect(Collectors.joining(",", "(", ")"));
            // 使String的格式为 (123,123)
            collect1 = collect1.substring(1,collect1.length()-1);
            list.add(collect1);
        });
//        System.out.println(list.get(0));
//        System.out.println(list.size());
        return list;
    }
}
